package org.wheel.module.core.util;

import cn.hutool.core.util.TypeUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * Class工具类
 */
public class ClassUtil {

    /** 常用基础类型（原始类型 + 包装类型 + String + 常见时间/数学类型） */
    private static final Set<Class<?>> BASIC_TYPES = Set.of(
            // 原始类型
            boolean.class, byte.class, char.class, short.class,
            int.class, long.class, float.class, double.class,
            // 包装类型
            Boolean.class, Byte.class, Character.class, Short.class,
            Integer.class, Long.class, Float.class, Double.class,
            // 其他常用
            String.class, java.math.BigDecimal.class, java.math.BigInteger.class,
            java.util.Date.class, java.time.LocalDate.class, java.time.LocalDateTime.class
    );

    /**
     * 返回 true 表示 clazz 不是基础类型
     */
    public static boolean isBasicType(Class<?> clazz) {
        if(clazz == null){
            return false;
        }
        // 处理数组类型
        if (clazz.isArray()) {
            return isBasicType(clazz.getComponentType());
        }
        return BASIC_TYPES.contains(clazz);
    }

    /**
     * 返回 true 表示 clazz 不是基础类型
     */
    public static boolean isNotBasicType(Class<?> clazz) {
        return !isBasicType(clazz);
    }

    /**
     * 获取实现类所实现目标接口的泛型参数（默认取第一个泛型T）
     * @param implClass 实现类的Class（如UserDao.class）
     * @param targetInterface 目标接口的Class（如BaseDao.class）
     * @return 泛型参数的Class（如User.class），未找到则返回null
     */
    public static Class<?> getInterfaceGenericType(Class<?> implClass, Class<?> targetInterface) {
        // 1. 获取实现类的所有接口类型（带泛型，如BaseDao<User>）
        Type[] genericInterfaces = implClass.getGenericInterfaces();
        if (genericInterfaces == null || genericInterfaces.length == 0) {
            return null;
        }

        // 2. 遍历接口类型，找到目标接口的ParameterizedType
        for (Type type : genericInterfaces) {
            // 检查是否是带泛型的接口（ParameterizedType）
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                // 检查该接口的原始类型是否等于目标接口（如BaseDao.class）
                if (parameterizedType.getRawType().equals(targetInterface)) {
                    // 3. 提取该接口的泛型参数数组（如[User.class]）
                    Type[] typeArguments = TypeUtil.getTypeArguments(parameterizedType);
                    if (typeArguments != null && typeArguments.length > 0) {
                        // 4. 返回第一个泛型参数（默认取T），转换为Class
                        Type genericType = typeArguments[0];
                        if (genericType instanceof Class) {
                            return (Class<?>) genericType;
                        }
                    }
                }
            }
        }

        // 未找到目标接口的泛型参数，返回null
        return null;
    }

    /**
     * 获取当前对象的接口泛型Class
     */
    public static Class<?> getCurrentGenericClass(Object obj, Class<?> interfaceClass) {
        return getInterfaceGenericType(obj.getClass(), interfaceClass);
    }


    /**
     * 获取实现类所实现目标接口的指定索引泛型参数
     * @param implClass 实现类的Class
     * @param targetInterface 目标接口的Class
     * @param index 泛型参数索引（从0开始）
     * @return 泛型参数的Class，未找到则返回null
     */
    public static Class<?> getInterfaceGenericType(Class<?> implClass, Class<?> targetInterface, int index) {
        if (implClass == null || targetInterface == null || index < 0) {
            return null;
        }

        try {
            // 1. 获取实现类的所有泛型接口
            Type[] genericInterfaces = implClass.getGenericInterfaces();

            // 2. 遍历所有接口，寻找目标接口
            for (Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof ParameterizedType) {
                    ParameterizedType paramType = (ParameterizedType) genericInterface;

                    // 3. 检查原始类型是否匹配目标接口
                    if (paramType.getRawType().equals(targetInterface)) {
                        // 4. 使用TypeUtil获取泛型参数
                        Type[] typeArguments = TypeUtil.getTypeArguments(paramType);

                        if (typeArguments != null && typeArguments.length > index) {
                            Type genericType = typeArguments[index];
                            return convertTypeToClass(genericType);
                        }
                    }
                }
            }

            // 5. 如果没有找到，检查父类是否实现了目标接口
            Class<?> superclass = implClass.getSuperclass();
            if (superclass != null && !superclass.equals(Object.class)) {
                return getInterfaceGenericType(superclass, targetInterface, index);
            }

        } catch (Exception e) {
            // 记录日志或处理异常
            System.err.println("获取接口泛型类型失败: " + e.getMessage());
        }

        return null;
    }

    /**
     * 从父类获取泛型类型（支持多层继承和接口实现）
     * @param implClass 实现类的Class
     * @param targetInterface 目标接口的Class
     * @return 泛型参数的Class，未找到则返回null
     */
    public static Class<?> getGenericTypeFromSuperclass(Class<?> implClass, Class<?> targetInterface) {
        return getGenericTypeFromSuperclass(implClass, targetInterface, 0);
    }

    /**
     * 从父类获取指定索引的泛型类型
     * @param implClass 实现类的Class
     * @param targetInterface 目标接口的Class
     * @param index 泛型参数索引
     * @return 泛型参数的Class，未找到则返回null
     */
    public static Class<?> getGenericTypeFromSuperclass(Class<?> implClass, Class<?> targetInterface, int index) {
        if (implClass == null || targetInterface == null || index < 0) {
            return null;
        }

        try {
            // 1. 获取直接父类的泛型类型
            Type genericSuperclass = implClass.getGenericSuperclass();

            if (genericSuperclass instanceof ParameterizedType) {
                ParameterizedType paramType = (ParameterizedType) genericSuperclass;
                Class<?> rawType = (Class<?>) paramType.getRawType();

                // 2. 检查父类是否直接实现了目标接口
                List<Class<?>> genericTypes = extractGenericTypesFromSuperclass(
                        paramType, rawType, targetInterface, index);

                if (!genericTypes.isEmpty()) {
                    return genericTypes.get(0);
                }

                // 3. 递归检查父类的父类
                Class<?> result = getGenericTypeFromSuperclass(rawType, targetInterface, index);
                if (result != null) {
                    return result;
                }
            }

            // 4. 如果没有泛型父类，检查普通父类
            Class<?> superclass = implClass.getSuperclass();
            if (superclass != null && !superclass.equals(Object.class)) {
                return getGenericTypeFromSuperclass(superclass, targetInterface, index);
            }

        } catch (Exception e) {
            System.err.println("从父类获取泛型类型失败: " + e.getMessage());
        }

        return null;
    }

    /**
     * 从父类中提取泛型类型（核心逻辑）
     */
    private static List<Class<?>> extractGenericTypesFromSuperclass(
            ParameterizedType paramType, Class<?> rawType, Class<?> targetInterface, int index) {

        List<Class<?>> result = new ArrayList<>();

        // A. 检查父类本身是否直接实现了目标接口
        Type[] genericInterfaces = rawType.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType interfaceParamType = (ParameterizedType) genericInterface;

                if (interfaceParamType.getRawType().equals(targetInterface)) {
                    Type[] typeArguments = TypeUtil.getTypeArguments(interfaceParamType);
                    if (typeArguments != null && typeArguments.length > index) {
                        Class<?> genericClass = convertTypeToClass(typeArguments[index]);
                        if (genericClass != null) {
                            result.add(genericClass);
                        }
                    }
                }
            }
        }

        // B. 如果父类没有直接实现，检查父类的泛型参数是否匹配目标接口
        Type[] actualTypeArguments = paramType.getActualTypeArguments();
        if (actualTypeArguments.length > index) {
            Type actualType = actualTypeArguments[index];

            // 如果是Class类型，直接返回
            if (actualType instanceof Class) {
                result.add((Class<?>) actualType);
            }
        }

        return result;
    }

    /**
     * 将Type转换为Class（处理各种Type子类）
     */
    private static Class<?> convertTypeToClass(Type type) {
        if (type instanceof Class) {
            return (Class<?>) type;
        } else if (type instanceof ParameterizedType) {
            // 处理嵌套泛型，如List<String>，返回List.class
            return (Class<?>) ((ParameterizedType) type).getRawType();
        }
        // 对于TypeVariable、WildcardType等其他类型，暂时返回null
        return null;
    }

    /**
     * 获取实现类所有实现的接口的泛型类型列表
     */
    public static List<Class<?>> getAllInterfaceGenericTypes(Class<?> implClass, Class<?> targetInterface) {
        List<Class<?>> result = new ArrayList<>();

        if (implClass == null || targetInterface == null) {
            return result;
        }

        // 1. 从直接接口获取
        Type[] genericInterfaces = implClass.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType paramType = (ParameterizedType) genericInterface;

                if (paramType.getRawType().equals(targetInterface)) {
                    Type[] typeArguments = TypeUtil.getTypeArguments(paramType);
                    if (typeArguments != null) {
                        for (Type typeArg : typeArguments) {
                            Class<?> genericClass = convertTypeToClass(typeArg);
                            if (genericClass != null) {
                                result.add(genericClass);
                            }
                        }
                    }
                }
            }
        }

        // 2. 从父类获取
        Class<?> superclass = implClass.getSuperclass();
        if (superclass != null && !superclass.equals(Object.class)) {
            result.addAll(getAllInterfaceGenericTypes(superclass, targetInterface));
        }

        return result;
    }

    /**
     * 安全获取泛型类型（优先从接口，其次从父类）
     */
    public static Class<?> safeGetGenericType(Class<?> implClass, Class<?> targetInterface) {
        return safeGetGenericType(implClass, targetInterface, 0);
    }

    /**
     * 安全获取指定索引的泛型类型
     */
    public static Class<?> safeGetGenericType(Class<?> implClass, Class<?> targetInterface, int index) {
        // 优先从直接接口获取
        Class<?> result = getInterfaceGenericType(implClass, targetInterface, index);

        if (result == null) {
            result = getGenericTypeFromSuperclass(implClass, targetInterface, index);
        }

        return result;
    }

    /**
     * 获取当前集合对象的泛型类型
     * @param object 集合对象
     * @return 泛型类型
     */
    public static Type getGenericType(Object object) {
        if (object == null) {
            return null;
        }

        Type type = object.getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            return type;
        }

        Type[] genericInterfaces = object.getClass().getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                return genericInterface;
            }
        }

        return null;
    }
}
